﻿using System.Collections.Specialized;
using System.Net;
using Fvs_Service.Core;
using Fvs_Service.Net;

namespace Fvs_Service
{
    public class VisibilityLevel
    {
        public byte Level { get; set; }
        public short Visibility { get; set; }
        public byte Temp { get; set; }
        public byte FogLight { get; set; }
        public short On { get; set; }
        public short Off { get; set; }
        public byte Red { get; set; }
        public byte Blind { get; set; }
        public byte RedLight { get; set; }
    };

    public class Lamp
    {
        public byte Id { get; set; }
        //控制
        //工作模式
        public byte _workMode { get; set; }
        //报警功能
        public byte _warning { get; set; }
        //开关
        public byte _switch1 { get; set; }
        public byte _switch2 { get; set; }
        //雷达
        public byte _radar { get; set; }

        public short _startAddress1 { get; set; }
        public short _stopAddress1 { get; set; }

        public short _startAddress2 { get; set; }
        public short _stopAddress2 { get; set; }

        //数据
        //亮度等级
        public byte _fogLight { get; set; }
        //亮灯时长
        public short _on { get; set; }
        //灭灯时长
        public short _off { get; set; }
        //红灯延时
        public byte _red { get; set; }
        //盲区延时
        public byte _blind { get; set; }
        //红色警示灯数量
        public byte _redLight { get; set; }
        //巡检时间
        public byte _inspection { get; set; }

        public int Visibility { get; set; }

        //能见度等级
        public readonly List<VisibilityLevel> _levels = new List<VisibilityLevel>();

    }

    public class Relay_Response
    {
        [SerializeIndex(1)]
        public byte Head { get; set; }
        [SerializeIndex(2)]
        public byte Address { get; set; }
        [SerializeIndex(3)]
        public byte Id { get; set; }
        [SerializeIndex(4)]
        public int Data { get; set; }
        [SerializeIndex(5)]
        public byte Sum { get; set; }
    }

    public class LampMaid:SocketMaid
    {
        private readonly Dictionary<SocketChannel, Lamp> _lamps = new Dictionary<SocketChannel, Lamp>();

        public BitVector32 _vector32;

        public SocketChannel AddLampConnectEndPoint(IPEndPoint endPoint,byte lampId)
        {
            SocketChannel channel=AddConnectEndPoint(new VirtualLampHandler(), endPoint);
            _lamps[channel] = new Lamp
            {
                Id = lampId
            };
            channel.Received += LampReceiveHandler;

            return channel;
        }

        private void LampReceiveHandler(object sender, ReceivedEventArgs e)
        {
            byte protocolId = e.Buffer[2];
            Lamp lamp = _lamps[e.Channel];
            if (protocolId == 0x03)
            {
                Handle03(e, lamp);
            }
            else if (protocolId == 0x05)
            {
                Handle05(e, lamp);
            }
            else if (protocolId == 0x07)
            {
                Handle07(e, lamp);
            }
            else if (protocolId == 0x09)
            {
                Handle09(e, lamp);
            }
            else if (protocolId == 0x0b)
            {
                Handle0b(e, lamp);
            }
            else if (protocolId == 0x0f)
            {
                Handle0f(e, lamp);
            }
            else if (protocolId == 0x11)
            {
                Handle11(e, lamp);
            }
            else if (protocolId == 0x21)
            {
                Handle21(e, lamp);
            }
            else if (protocolId == 0x25)
            {
                Handle25(e, lamp);
            }
            else if (protocolId == 0x27)
            {
                Handle27(e, lamp);
            }
        }

        public void AddRelayConnectEndPoint(IPEndPoint endPoint)
        {
            SocketChannel channel = AddConnectEndPoint(new VirtualRelayHandler(), endPoint);
            channel.Received += RelayReceiveHandler;
        }

        private void RelayReceiveHandler(object sender, ReceivedEventArgs e)
        {
            byte id = e.Buffer[2];
            int data = 0;
            if (id == (char)0x10)
            {
                data = _vector32.Data;
            }
            else if (id == (char)0x11)
            {
                int index = e.Buffer[6];
                _vector32[index - 1] = false;
            }
            else if (id == (char)0x12)
            {
                int index = e.Buffer[6];
                _vector32[index - 1] = true;
            }
            else
            {
                return;
            }
            Relay_Response response = new Relay_Response
            {
                Head = 0x22,
                Address = 0x00,
                Id = id,
                Data = data,
                Sum = 0
            };

            List<byte> responseBuffer = ByteFormatter.Serialize(response);
            int sum = 0;
            for (int i = 0; i < 7; ++i)
            {
                sum += responseBuffer[i];
            }
            responseBuffer[7] = Convert.ToByte(sum);
            e.Channel.Send(null, responseBuffer);
        }

        void SendResponse(ReceivedEventArgs args,Lamp lamp, byte id)
        {
            List<byte> buffer = new List<byte> { 0x90, lamp.Id, id, 0xff };
            args.Channel.Send(null, buffer);
        }

        void Handle03(ReceivedEventArgs args,Lamp lamp)
        {
            int size = args.Buffer.Count;
            if (size < 5)
            {
                return;
            }

            byte workMode = args.Buffer[3];


            if (workMode >= 1 && workMode <= 5)
            {
                lamp._workMode = workMode;
                //数据有效
                if (workMode >= 1 && workMode <= 3)
                {
                    if (size < 13)
                    {
                        return;
                    }
                    lamp._fogLight = args.Buffer[4];
                    lamp._on = (short)(args.Buffer[6] * 128 + args.Buffer[5]);
                    lamp._off = (short)(args.Buffer[8] * 128 + args.Buffer[7]);
                    lamp._red = args.Buffer[9];
                    lamp._blind = args.Buffer[10];
                    lamp._redLight = args.Buffer[11];
                }
            }
            else if (workMode == 0x06)
            {
                lamp._warning = 0;
            }
            else if (workMode == 0x07)
            {
                lamp._warning = 1;
            }
            else if (workMode == 0x08)
            {
                lamp._switch1 = 1;
            }
            else if (workMode == 0x09)
            {
                lamp._switch1 = 0;
            }
            else if (workMode == 0x0a)
            {
                lamp._switch2 = 1;
            }
            else if (workMode == 0x0b)
            {
                lamp._switch2 = 0;
            }
            else if (workMode == 0x0c)
            {
                lamp._radar = 1;
            }
            else if (workMode == 0x0d)
            {
                lamp._radar = 0;
            }
            SendResponse(args, lamp, 0x03);
        }

        void Handle05(ReceivedEventArgs args,Lamp lamp)
        {
            SendResponse(args, lamp, 0x05);
        }

        void Handle07(ReceivedEventArgs args,Lamp lamp)
        {
            if (args.Buffer.Count < 125)
            {
                return;
            }
            int index = 3;
            lamp._levels.Clear();

            for (int i = 0; i < 10; ++i)
            {
                VisibilityLevel level = new VisibilityLevel
                {
                    Level = args.Buffer[index],
                    Visibility = (short)(args.Buffer[index + 2] * 128 + args.Buffer[index + 1]),
                    Temp = args.Buffer[index + 3],
                    FogLight = args.Buffer[index + 4],
                    On = (short)(args.Buffer[index + 6] * 128 + args.Buffer[index + 5]),
                    Off = (short)(args.Buffer[index + 8] * 128 + args.Buffer[index + 7]),
                    Red = args.Buffer[index + 9],
                    Blind = args.Buffer[index + 10],
                    RedLight = args.Buffer[index + 11]
                };
                lamp._levels.Add(level);
                index += 12;
            }
            SendResponse(args, lamp, 0x07);
        }

        void Handle09(ReceivedEventArgs args,Lamp lamp)
        {
            int size = args.Buffer.Count;
            if (size < 4)
            {
                return;
            }

            List<byte> sendBuffer = new List<byte> { 0x90, lamp.Id, 0x09 };

            if (lamp._levels.Count == 10)
            {
                for (int i = 0; i < 10; ++i)
                {
                    sendBuffer.Add(lamp._levels[i].Level);
                    sendBuffer.Add((byte)(lamp._levels[i].Visibility % 128));
                    sendBuffer.Add((byte)(lamp._levels[i].Visibility / 128));
                    sendBuffer.Add(lamp._levels[i].Temp);
                    sendBuffer.Add(lamp._levels[i].FogLight);
                    sendBuffer.Add((byte)(lamp._levels[i].On % 128));
                    sendBuffer.Add((byte)(lamp._levels[i].On / 128));
                    sendBuffer.Add((byte)(lamp._levels[i].Off % 128));
                    sendBuffer.Add((byte)(lamp._levels[i].Off / 128));
                    sendBuffer.Add(lamp._levels[i].Red);
                    sendBuffer.Add(lamp._levels[i].Blind);
                    sendBuffer.Add(lamp._levels[i].RedLight);
                }
            }
            else
            {
                for (int i = 0; i < 10; ++i)
                {
                    sendBuffer.Add((byte)i);
                    sendBuffer.Add(0);
                    sendBuffer.Add(0);
                    sendBuffer.Add(0);
                    sendBuffer.Add(0);
                    sendBuffer.Add(0);
                    sendBuffer.Add(0);
                    sendBuffer.Add(0);
                    sendBuffer.Add(0);
                    sendBuffer.Add(0);
                    sendBuffer.Add(0);
                    sendBuffer.Add(0);
                }
            }
            sendBuffer.Add(ByteConvert.Xor(sendBuffer, 3, sendBuffer.Count - 3));
            sendBuffer.Add(0xff);
            args.Channel.Send(null, sendBuffer);
        }

        void Handle0b(ReceivedEventArgs args,Lamp lamp)
        {
            int size = args.Buffer.Count;
            if (size < 6)
            {
                return;
            }
            if (args.Buffer[3] == 0 && args.Buffer[4] == 0)
            {
                List<byte> sendBuffer = new List<byte>
                {
                    0x90,
                    lamp.Id,
                    0x0b,
                    0x00,
                    0x00
                };
                byte mode = 0;
                if (lamp._warning == 0)
                {
                    mode |= 0x01;
                }

                if (lamp._switch1 == 1)
                {
                    mode |= 0x10;
                }

                if (lamp._switch2 == 1)
                {
                    mode |= 0x20;
                }

                if (lamp._workMode != 4)
                {
                    mode |= 0x40;
                }
                sendBuffer.Add(mode);
                mode = 0;
                if (lamp._radar == 1)
                {
                    mode |= 0x01;
                }
                //能见度检测仪失联
                mode |= 0x02;
                sendBuffer.Add(mode);
                sendBuffer.Add(lamp._workMode);
                //能见度检测仪失联
                sendBuffer.Add(0x7d);
                sendBuffer.Add(lamp._fogLight);
                sendBuffer.Add((byte)(lamp._on % 128));
                sendBuffer.Add((byte)(lamp._on / 128));
                sendBuffer.Add((byte)(lamp._off % 128));
                sendBuffer.Add((byte)(lamp._off / 128));
                sendBuffer.Add(lamp._red);
                sendBuffer.Add(lamp._blind);
                sendBuffer.Add(lamp._redLight);
                sendBuffer.Add(0xff);
                args.Channel.Send(null, sendBuffer);
            }
        }

        void Handle0f(ReceivedEventArgs args,Lamp lamp)
        {
            int size = args.Buffer.Count;
            if (size != 12)
            {
                return;
            }
            lamp._startAddress1 = Convert.ToInt16(args.Buffer[3] + args.Buffer[4] * 128);
            lamp._stopAddress1 = Convert.ToInt16(args.Buffer[5] + args.Buffer[6] * 128);
            lamp._startAddress2 = Convert.ToInt16(args.Buffer[7] + args.Buffer[8] * 128);
            lamp._stopAddress2 = Convert.ToInt16(args.Buffer[9] + args.Buffer[10] * 128);
            SendResponse(args, lamp, 0x0f);
        }

        void Handle11(ReceivedEventArgs args,Lamp lamp)
        {
            int size = args.Buffer.Count;
            if (size < 4)
            {
                return;
            }

            List<byte> sendBuffer = new List<byte>
            {
                0x90,
                lamp.Id,
                0x11,
                (byte) (lamp._startAddress1 % 128),
                (byte) (lamp._startAddress1 / 128),
                (byte) (lamp._stopAddress1 % 128),
                (byte) (lamp._stopAddress1 / 128),
                (byte) (lamp._startAddress2 % 128),
                (byte) (lamp._startAddress2 / 128),
                (byte) (lamp._stopAddress2 % 128),
                 (byte) (lamp._stopAddress2 / 128),
                lamp._inspection,
                 0xFF
            };
            args.Channel.Send(null, sendBuffer);
        }

        void Handle21(ReceivedEventArgs args,Lamp lamp)
        {

            if (args.Buffer.Count < 8)
            {
                return;
            }

            byte start1 = args.Buffer[3];
            byte start2 = args.Buffer[4];
            byte end1 = args.Buffer[5];
            byte end2 = args.Buffer[6];

            short start = Convert.ToInt16(start2 * 128 + start1);
            short end = Convert.ToInt16(end2 * 128 + end1);

            List<byte> sendBuffer = new List<byte>
            {
                0x90,
                lamp.Id,
                0x21
            };
            for (int i = start; i <= end; ++i)
            {
                sendBuffer.Add(0x00);
                sendBuffer.Add(0x00);
                sendBuffer.Add(0x00);
                sendBuffer.Add(0x00);
                sendBuffer.Add(0x00);
                sendBuffer.Add(0x00);
            }
            sendBuffer.Add(0xff);
            args.Channel.Send(null, sendBuffer);
        }

        void Handle25(ReceivedEventArgs args,Lamp lamp)
        {
            if (args.Buffer.Count < 5)
            {
                return;
            }

            lamp._inspection = args.Buffer[3];
            SendResponse(args, lamp, 0x25);
        }

        void Handle27(ReceivedEventArgs args,Lamp lamp)
        {
            if (args.Buffer.Count < 4)
            {
                return;
            }

            List<byte> temp = new List<byte>
            {
               0x90,
                lamp.Id,
               0x27,
               0x00,
               0x00,
               (byte) (lamp.Visibility % 128),
               (byte) (lamp.Visibility / 128),
               0x00,
               0x00,
               0x00,
                0x00,
                0x00,
                0xff
            };
            args.Channel.Send(null, temp);
        }


    }
}
